home *** CD-ROM | disk | FTP | other *** search
/ Aminet 33 / Aminet 33 - October 1999.iso / Aminet / util / misc / VMM_src.lha / VMM / VM_Manager_Init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-12-22  |  26.7 KB  |  1,015 lines

  1. #include <exec/types.h>
  2. #include "defs.h"
  3. #define MANAGER_PRIV
  4. #include "Manager_Priv.h"
  5.  
  6. static char rcsid [] = "$Id: VM_Manager_Init.c,v 1.8 95/12/16 18:37:04 Martin_Apel Exp $";
  7.  
  8. /*********************************************************************/
  9.  
  10. PRIVATE int OpenLibs (void)
  11.  
  12. {
  13. SysBase = *((struct ExecBase**)4L);
  14. if (SysBase->LibNode.lib_Version < 37)
  15.   return (ERR_LOW_VERSION);
  16.  
  17. if ((DOSBase = (struct DosLibrary*)OpenLibrary ("dos.library", 37L)) == NULL)
  18.   return (ERR_NO_DOS);
  19.  
  20. if ((IntuitionBase = OpenLibrary ("intuition.library", 37L)) == NULL)
  21.   return (ERR_NO_INTUITION);
  22.  
  23. if ((GfxBase = (struct GfxBase*)OpenLibrary ("graphics.library", 37L)) == NULL)
  24.   return (ERR_NO_GFX);
  25.  
  26. if ((UtilityBase = OpenLibrary ("utility.library", 37L)) == NULL)
  27.   return (ERR_NO_UTILITY);
  28.  
  29. if ((ExpansionBase = OpenLibrary ("expansion.library", 37L)) == NULL)
  30.   return (ERR_NO_EXPANSION);
  31.  
  32. if ((CxBase = OpenLibrary ("commodities.library", 37L)) == NULL)
  33.   return (ERR_NO_COMMODITIES);
  34.  
  35. if ((RexxSysBase = OpenLibrary ("rexxsyslib.library", 36L)) == NULL)
  36.   return (ERR_NO_REXX);
  37.  
  38. LocaleBase = OpenLibrary ("locale.library", 38L);
  39.  
  40. return (SUCCESS);
  41. }
  42.  
  43. /*********************************************************************/
  44.  
  45. PRIVATE BOOL ReceiveInitMsg (void)
  46.  
  47. {
  48. struct VMMsg *InitMsg;
  49. BOOL Success;
  50.  
  51. Wait (1L << InitPort->mp_SigBit);
  52.  
  53. if ((InitMsg = (struct VMMsg*)GetMsg (InitPort)) == NULL)
  54.   {
  55.   PRINT_DEB ("VM_Manager: Init failure", 0L);
  56.   return (FALSE);
  57.   }
  58.  
  59. if (InitMsg->VMCommand == VMCMD_InitReady)
  60.   Success = TRUE;
  61. else
  62.   Success = FALSE;
  63.  
  64. if (InitMsg->ReplySignal == NULL)
  65.   {
  66.   PRINT_DEB ("Freeing InitMsg", 0L);
  67.   FreeMem (InitMsg, sizeof (struct VMMsg));
  68.   }
  69. else
  70.   {
  71.   PRINT_DEB ("Returning init msg to sender", 0L);
  72.   Signal (InitMsg->VMSender, 1L << InitMsg->ReplySignal);
  73.   }
  74. return (Success);
  75. }
  76.  
  77. /*********************************************************************/
  78.  
  79. PRIVATE int LaunchPageHandler (void)
  80.  
  81. {
  82. struct TagItem PH_Tags [] =
  83. { { NP_Entry, (ULONG)PageHandler },
  84.   { NP_Name, (ULONG)PAGEHANDLER_NAME },
  85.   { NP_Priority, 19L },
  86.   { NP_StackSize, 6000L },
  87.   { TAG_DONE, 0L } };
  88.  
  89. switch (CurrentConfig.PageDev)
  90.   {
  91.   case PD_FILE:
  92.   case PD_PSEUDOPART:
  93.     if ((PageHandlerProcess = CreateNewProc (PH_Tags)) == NULL)
  94.       return (ERR_NOT_ENOUGH_MEM);
  95.     PageHandlerTask = (struct Task*)PageHandlerProcess;
  96.     break;
  97.  
  98.   case PD_PART:
  99.     if ((PageHandlerTask = CreateTask (PAGEHANDLER_NAME, 19L, PageHandler, 4000L))
  100.                    == NULL)
  101.       return (ERR_NOT_ENOUGH_MEM);
  102.     break;
  103.  
  104. #ifdef DEBUG
  105.   default:
  106.     PRINT_DEB ("LaunchPageHandler: Unknown paging device", 0L);
  107.     ColdReboot ();
  108. #endif
  109.   }
  110.  
  111. if (!ReceiveInitMsg ())
  112.   return (ERR_MSG_POSTED);
  113. return (SUCCESS);
  114. }
  115.  
  116. /*********************************************************************/
  117.  
  118. PRIVATE int LaunchPrePager (void)
  119.  
  120. {
  121. struct TagItem PP_Tags [] =
  122. { { NP_Entry, (ULONG)PrePager },
  123.   { NP_Name, (ULONG)PREPAGER_NAME },
  124.   { NP_Priority, 20L },
  125.   { NP_StackSize, 4000L },
  126.   { TAG_DONE, 0L } };
  127.  
  128. switch (CurrentConfig.PageDev)
  129.   {
  130.   case PD_FILE:
  131.     if ((PrePagerProcess = CreateNewProc (PP_Tags)) == NULL)
  132.       return (ERR_NOT_ENOUGH_MEM);
  133.     PrePagerTask = (struct Task*)PrePagerProcess;
  134.     break;
  135.  
  136.   case PD_PART:
  137.   case PD_PSEUDOPART:
  138.     if ((PrePagerTask = CreateTask (PREPAGER_NAME, 20L, PrePager, 4000L)) == NULL)
  139.       return (ERR_NOT_ENOUGH_MEM);
  140.     break;
  141.  
  142. #ifdef DEBUG
  143.   default:
  144.     PRINT_DEB ("LaunchPrePager: Unknown paging device", 0L);
  145.     ColdReboot ();
  146. #endif
  147.   }
  148.  
  149. if (!ReceiveInitMsg ())
  150.   return (ERR_MSG_POSTED);
  151. return (SUCCESS);
  152. }
  153.  
  154. /*********************************************************************/
  155.  
  156. int LaunchStat (void)
  157.  
  158. {
  159. DISABLE_VM;
  160. if ((StatTask = CreateTask (STAT_NAME, 5L, Statistics, 4000L)) == NULL)
  161.   {
  162.   PRINT_DEB ("Could not create statistics task", 0L);
  163.   ENABLE_VM;
  164.   return (ERR_NOT_ENOUGH_MEM);
  165.   }
  166.  
  167. if (!ReceiveInitMsg ())
  168.   {
  169.   PRINT_DEB ("ReceiveInitMsg failed", 0L);
  170.   ENABLE_VM;
  171.   return (ERR_MSG_POSTED);
  172.   }
  173.  
  174. ENABLE_VM;
  175. return (SUCCESS);
  176. }
  177.  
  178. /*********************************************************************/
  179.  
  180. PRIVATE void adjust_priority (void)
  181.  
  182. {
  183. char *PagingDevName;
  184. struct Task *PagingDevTask;
  185. LONG PagingDevPri;
  186.  
  187. /* If the paging device has its own task, the priority of the page handler
  188.  * is one below that task, otherwise priority 19 is taken
  189.  * It is assumed that the task handling the IO for the device is named
  190.  * the same as the device itself
  191.  */
  192.  
  193. PagingDevName = PagingDevParams.device->dd_Library.lib_Node.ln_Name;
  194. if ((PagingDevTask = FindTask (PagingDevName)) != NULL)
  195.   {
  196.   PagingDevPri = PagingDevTask->tc_Node.ln_Pri;
  197.   SetTaskPri (PageHandlerTask, PagingDevPri - 1);
  198.   SetTaskPri (PrePagerTask, PagingDevPri - 2);
  199.   }
  200. else
  201.   {
  202.   SetTaskPri (PageHandlerTask, 19L);
  203.   SetTaskPri (PrePagerTask, 18L);
  204.   }
  205. }  
  206.  
  207. /*********************************************************************/
  208.  
  209. PRIVATE int InitTrapstructs (void)
  210.  
  211. {
  212. int i;
  213.  
  214. NewList (&Free);
  215. NewList (&PageReq);
  216. NewList (&InTransit);
  217.  
  218. for (i = 0; i < MAX_FAULTS; i++)
  219.   {
  220.   TrapInfo [i].TmpStackSwap.stk_Lower = &(TrapInfo [i].TmpStack [0]);
  221.   TrapInfo [i].TmpStackSwap.stk_Upper = (ULONG)&(TrapInfo [i].TmpStack [TMP_STACKSIZE]);
  222.   TrapInfo [i].TmpStackSwap.stk_Pointer = &(TrapInfo [i].TmpStack [TMP_STACKSIZE]);
  223.  
  224.   AddHead (&Free, (struct Node*)&(TrapInfo [i]));
  225.   }
  226.  
  227. return (SUCCESS);
  228. }
  229.  
  230.  
  231. /*********************************************************************/
  232.  
  233. PRIVATE void patch (void)
  234.  
  235. {
  236. Forbid ();
  237. PRINT_DEB ("Patching LoadSeg ()", 0L);
  238. OrigLoadSeg = (void (*) ()) SetFunction ((struct Library*)DOSBase, -0x96, 
  239.                               (ULONG (*) ()) LoadSegPatch);
  240.  
  241. PRINT_DEB ("Patching NewLoadSeg ()", 0L);
  242. OrigNewLoadSeg = (void (*) ()) SetFunction ((struct Library*)DOSBase, -0x300, 
  243.                               (ULONG (*) ()) NewLoadSegPatch);
  244.  
  245. #ifdef DEBUG
  246. PRINT_DEB ("Patching RemTask ()", 0L);
  247. OrigRemTask = (void (*) ()) SetFunction ((struct Library*)SysBase,
  248.                                    -0x120, (ULONG (*) ()) RemTaskPatch);
  249.  
  250. /*
  251. PRINT_DEB ("Patching StackSwap ()", 0L);
  252. OrigStackSwap = (void (*) ()) SetFunction ((struct Library*)SysBase,
  253.                                    -0x2dc, (ULONG (*) ()) StackSwapPatch);
  254. */
  255.  
  256. PRINT_DEB ("Patching Open ()", 0L);
  257. OrigOpen = (void (*) ()) SetFunction ((struct Library*)DOSBase,
  258.                                    -0x1e, (ULONG (*) ()) OpenPatch);
  259.  
  260. #endif
  261.  
  262. if (CurrentConfig.PatchWB)
  263.   {
  264.   PRINT_DEB ("Patching SetWindowTitles ()", 0L);
  265.   OrigSetWindowTitles = (void (*) ()) SetFunction ((struct Library*)IntuitionBase,
  266.                                      -0x114, (ULONG (*) ()) SetWindowTitlesPatch);
  267.   }
  268.   
  269. if (ProcessorType == PROC_68030)
  270.   {
  271.   PRINT_DEB ("Patching ColdReboot ()", 0L);
  272.   OrigColdReboot = (void (*) ()) SetFunction ((struct Library*)SysBase,
  273.                                      -0x2d6, (ULONG (*) ()) ColdRebootPatch);
  274.   }
  275.  
  276. PRINT_DEB ("Patching CachePreDMA ()", 0L);
  277. OrigCachePreDMA = (void (*) ()) SetFunction ((struct Library*)SysBase, 
  278.                                    -0x2fa, (ULONG (*) ()) CachePreDMAPatch);
  279.  
  280. PRINT_DEB ("Patching CachePostDMA ()", 0L);
  281. OrigCachePostDMA = (void (*) ()) SetFunction ((struct Library*)SysBase, 
  282.                                    -0x300, (ULONG (*) ()) CachePostDMAPatch);
  283.  
  284. PRINT_DEB ("Patching Switch ()", 0L);
  285. OrigSwitch = (void (*) ()) SetFunction ((struct Library*)SysBase, 
  286.                                    -0x36, (ULONG (*) ()) SwitchPatch);
  287.  
  288. PRINT_DEB ("Patching AddTask ()", 0L);
  289. OrigAddTask = (void (*) ()) SetFunction ((struct Library*)SysBase,
  290.                                    -0x11a, (ULONG (*) ()) AddTaskPatch);
  291.  
  292. PRINT_DEB ("Patching Wait ()", 0L);
  293. OrigWait = (void (*) ()) SetFunction ((struct Library*)SysBase,
  294.                                    -0x13e, (ULONG (*) ()) WaitPatch);
  295.  
  296. PRINT_DEB ("Patching AvailMem ()", 0L);
  297. OrigAvailMem = (void (*) ()) SetFunction ((struct Library*)SysBase, -0xd8, 
  298.                               (ULONG (*) ()) AvailMemPatch);
  299.  
  300. PRINT_DEB ("Patching FreeMem ()", 0L);
  301. OrigFreeMem = (void (*) ()) SetFunction ((struct Library*)SysBase, -0xd2, 
  302.                               (ULONG (*) ()) FreeMemPatch);
  303.  
  304. PRINT_DEB ("Patching AllocMem ()", 0L);
  305. OrigAllocMem = (void (*) ()) SetFunction ((struct Library*)SysBase, -0xc6, 
  306.                               (ULONG (*) ()) AllocMemPatch);
  307.  
  308. PRINT_DEB ("Patching done", 0L);
  309. Permit ();
  310. }
  311.  
  312. /*********************************************************************/
  313.  
  314. PRIVATE BOOL PatchRamlib (void)
  315.  
  316. {
  317. struct MsgPort *ramlib_port;
  318. UWORD *ramlib_private;
  319. struct Task *RamLib;
  320.  
  321. ramlib_private = (UWORD*) SysBase->ex_RamLibPrivate;
  322.  
  323. if ((RamLib = FindTask ("ramlib")) == NULL)
  324.   {
  325.   PRINT_DEB ("PatchRamlib: Didn't find ramlib task", 0L);
  326.   return (FALSE);
  327.   }
  328.  
  329. /* Search the next 200 bytes for something that looks like a port. */
  330. while (ramlib_private < (UWORD*)SysBase->ex_RamLibPrivate + 100)
  331.   {
  332.   ramlib_port = (struct MsgPort*) ramlib_private;
  333.  
  334.   if (ramlib_port->mp_Flags == PA_SIGNAL &&
  335.       ramlib_port->mp_SigTask == RamLib)
  336.     {
  337.     /* Found the port. Find a free signal bit, mark it as used and enter it
  338.      * as the port bit into that port.
  339.      */
  340.     UBYTE signal_bit;
  341.  
  342.     if (ramlib_port->mp_SigBit != SIGB_SINGLE)
  343.       {
  344.       PRINT_DEB ("PatchRamlib: Patch has already been applied", 0L);
  345.       return (TRUE);
  346.       }
  347.  
  348.     signal_bit = 31;
  349.     Forbid ();
  350.     while (signal_bit > 15 && 
  351.           ((1L << signal_bit) & RamLib->tc_SigAlloc))
  352.       signal_bit--;
  353.  
  354.     if (signal_bit == 15)
  355.       {
  356.       Permit ();
  357.       PRINT_DEB ("PatchRamlib: All signal bits of ramlib task in use", 0L);
  358.       return (FALSE);
  359.       }
  360.  
  361.     RamLib->tc_SigAlloc |= (1L << signal_bit);
  362.     RamLib->tc_SigWait |= (1L << signal_bit);
  363.     ramlib_port->mp_SigBit = signal_bit;
  364.     Signal (RamLib, SIGF_SINGLE | (1L << signal_bit));
  365.     Permit ();
  366.     PRINT_DEB ("PatchRamlib: Successfully patched ramlib", 0L);
  367.     return (TRUE);
  368.     }
  369.   else      
  370.     ramlib_private++;
  371.   }
  372.  
  373. PRINT_DEB ("PatchRamlib: Didn't find ramlib's port", 0L);
  374. return (FALSE);
  375. }
  376.  
  377. /*********************************************************************/
  378.  
  379. int Init_VM_Manager (void)
  380.  
  381. {
  382. ULONG NeededForTables;
  383. struct Process *myself;
  384. struct VMMsg *StartupMsg;
  385. int rc;
  386.  
  387. if ((rc = OpenLibs ()) != SUCCESS)
  388.   return (rc);
  389.  
  390. #ifdef DEBUG
  391. if (!OpenDebugWindow ())
  392.   ReportError ("Debug buffer could not be installed\n"
  393.                "Resuming without debug information", ERR_CONTINUE);
  394. #endif
  395.  
  396. /* Wait for startup message */
  397. myself = (struct Process*)FindTask (NULL);
  398. PRINT_DEB ("Waiting for startup message", 0L);
  399. WaitPort (&(myself->pr_MsgPort));
  400. StartupMsg = (struct VMMsg*) GetMsg (&(myself->pr_MsgPort));
  401. CxParams = StartupMsg->StartupParams;
  402.  
  403. /* CxParams == NULL can happen if started from vmm.library */
  404. if (CxParams != NULL)
  405.   {
  406.   PRINT_DEB ("Received CxParams", 0L);
  407.   if (!(VMEnabled = CxParams->VMEnable))
  408.     DISABLE_VM;
  409.   ExtCxPort = CxParams->ExtCxPort;
  410.   CxSignal = AllocSignal (-1L);
  411.   PRINT_DEB ("Path for preferences file:", 0L);
  412.   PRINT_DEB (StartupMsg->StartupParams->PrefsPath, 0L);
  413.   Forbid ();
  414.   ExtCxPort->CxPort.mp_SigBit = CxSignal;
  415.   ExtCxPort->CxPort.mp_SigTask = FindTask (NULL);
  416.   Permit ();
  417.   }
  418.  
  419. PRINT_DEB ("Received startup message", 0L);
  420.  
  421. FreeMem (StartupMsg, sizeof (struct VMMsg));
  422.  
  423. if (!PatchRamlib ())
  424.   {
  425.   PRINT_DEB ("*** Could not install ramlib patch", 0L);
  426. #ifdef DEBUG
  427.   ReportError ("Ramlib patch could not be installed.\nPlease contact author "
  428.                "with output of\n'print_debug' and Kickstart version number", ERR_CONTINUE);
  429. #endif
  430.   }
  431.  
  432. NewList (&LoadingTasksList);
  433.  
  434. INIT_SEMA (&VirtMemSema);
  435.  
  436. CfgChangeSignal = AllocSignal (-1L);
  437. LockAckSignal = AllocSignal (-1L);
  438.  
  439. VM_ManagerProcess = (struct Process*)FindTask (NULL);
  440.  
  441. OpenVMMCatalog ();
  442.  
  443. if (SysBase->AttnFlags & AFF_68040)
  444.   {
  445.   PRINT_DEB ("Checking for 68060", 0L);
  446.   if (Is68060 ())
  447.     {
  448.     PRINT_DEB ("68060 detected", 0L);
  449.     ProcessorType = PROC_68060;
  450.     FlushVirt = (void (*) (ULONG)) EmptyFunc;
  451.     CPushP = CPushP60;
  452.     CPushL = CPushL60;
  453.     PFlushP = PFlushP60;
  454.     PFlushA = PFlushA60;
  455.     GenDescr = GenDescr60;
  456.     }
  457.   else
  458.     {
  459.     PRINT_DEB ("68040 detected", 0L);
  460.     ProcessorType = PROC_68040;
  461.     FlushVirt = (void (*) (ULONG)) EmptyFunc;
  462.     CPushP = CPushP40;
  463.     CPushL = CPushL40;
  464.     PFlushP = PFlushP40;
  465.     PFlushA = PFlushA40;
  466.     GenDescr = GenDescr40;
  467.     }
  468.   }
  469. else if (SysBase->AttnFlags & AFF_68030)
  470.   {
  471.   PRINT_DEB ("68030 detected", 0L);
  472.   ProcessorType = PROC_68030;
  473.   FlushVirt = (void (*) (ULONG)) CacheClearU;
  474.   CPushP = (void (*) (ULONG)) EmptyFunc;
  475.   CPushL = (void (*) (ULONG)) EmptyFunc;
  476.   PFlushP = PFlushP30;
  477.   PFlushA = PFlushA30;
  478.   GenDescr = GenDescr30;
  479.   }
  480. else if ((SysBase->AttnFlags & AFF_68020) && MMU68851 ())
  481.   {
  482.   PRINT_DEB ("68020 + 68851 detected", 0L);
  483.   ProcessorType = PROC_68851;
  484.   FlushVirt = (void (*) (ULONG)) CacheClearU;
  485.   CPushP = (void (*) (ULONG)) EmptyFunc;
  486.   CPushL = (void (*) (ULONG)) EmptyFunc;
  487.   PFlushP = PFlushP30;
  488.   PFlushA = PFlushA30;
  489.   GenDescr = GenDescr30;
  490.   }
  491. else
  492.   {
  493.   PRINT_DEB ("VM_Manager: Need 68060, 68040, 68030 or 68020+68851", 0L);
  494.   return (ERR_WRONG_CPU);
  495.   }
  496.  
  497. /* Figure out if we're running on an A3000. If yes we can force a hard
  498.  * rekick upon reboot if necessary.
  499.  */
  500. IsA3000 = ((GfxBase->ChipRevBits0 & SETCHIPREV_AA) == SETCHIPREV_ECS) &&
  501.            (ProcessorType == PROC_68030 ) && 
  502.            (ALIGN_DOWN ((*GenDescr) (0xF80000), PAGEALIGN) == 0x7f80000);
  503.  
  504. PRINT_DEB ("Initializing trapstructs", 0L);
  505.  
  506. if ((rc = InitTrapstructs ()) != SUCCESS)
  507.   return (rc);
  508.  
  509. PRINT_DEB ("Before MMU table", 0L);
  510.  
  511. if ((rc = SetupMMUTable ()) != SUCCESS)
  512.   {
  513.   PRINT_DEB ("Couldn't set up MMU table", 0L);
  514.   return (rc);
  515.   }
  516.  
  517. PRINT_DEB ("SetupMMUTable ready. Pagesize is %ld", PAGESIZE);
  518.  
  519. if ((InitPort = CreateMsgPort ()) == NULL)
  520.   {
  521.   PRINT_DEB ("VM_Manager: Couldn't allocate InitPort", 0L);
  522.   return (ERR_NOT_ENOUGH_MEM);
  523.   }
  524.   
  525. if ((VMPort = CreateMsgPort ()) == NULL)
  526.   {
  527.   PRINT_DEB ("VM_Manager: Couldn't allocate VMPort", 0L);
  528.   return (ERR_NOT_ENOUGH_MEM);
  529.   }
  530.  
  531. VMPort->mp_Node.ln_Pri = 0L;
  532. VMPort->mp_Node.ln_Name = VMPORTNAME;
  533. AddPort (VMPort);
  534.  
  535. PRINT_DEB ("VM_Manager: Public port added successfully", 0L);
  536.  
  537. if ((RexxPort = CreateMsgPort ()) == NULL)
  538.   {
  539.   PRINT_DEB ("VM_Manager: Couldn't allocate RexxPort", 0L);
  540.   return (ERR_NOT_ENOUGH_MEM);
  541.   }
  542.  
  543. RexxPort->mp_Node.ln_Pri = 0L;
  544. RexxPort->mp_Node.ln_Name = PROGNAME;   /* Rexx port should have the same
  545.                                          * name as the program. */
  546.  
  547. AddPort (RexxPort);
  548.  
  549. PRINT_DEB ("VM_Manager: Rexx port added successfully", 0L);
  550.  
  551. if ((rc = AllocAddressRange ()) != SUCCESS)
  552.   return (rc);
  553.  
  554. PRINT_DEB ("VM_Manager: Start of address space is %lx", VirtAddrStart);
  555. PRINT_DEB ("VM_Manager: End   of address space is %lx", VirtAddrEnd);
  556.  
  557. if ((rc = InitTaskTable ()) != SUCCESS)
  558.   return (rc);
  559.  
  560. if ((rc = InitTrackInfo ()) != SUCCESS)
  561.   return (rc);
  562.  
  563. if ((rc = ReadConfigFile ((CxParams != NULL) ? CxParams->ConfigPath : CFG_FILENAME)) != SUCCESS)
  564.   {
  565.   PRINT_DEB ("ReadConfigFile returned error %ld", (ULONG)rc);
  566.   return (rc);
  567.   }
  568.  
  569. PRINT_DEB ("VM_Manager: Config file successfully read", 0L);
  570.  
  571. AllowZorroIICaching ((BOOL)CurrentConfig.CacheZ2RAM);
  572. if ((rc = SwitchFastROM (CurrentConfig.FastROM)) != SUCCESS)
  573.   {
  574.   PRINT_DEB ("Init_VM_Manager: Error during turning on FastROM", 0L);
  575.   return (rc);
  576.   }
  577.  
  578. if ((rc = EnterTask (ERR_NAME, USE_NEVER, USE_NEVER, CNOSWAP, INSERT_FRONT)) != SUCCESS)
  579.   {
  580.   PRINT_DEB ("Init_VM_Manager: Couldn't enter task", 0L);
  581.   return (rc);
  582.   }
  583.  
  584. if (CurrentConfig.PageDev == PD_FILE)
  585.   {
  586.   if ((rc = EnterTask (PartitionName, USE_NEVER, USE_NEVER, CNOSWAP, INSERT_FRONT)) != SUCCESS)
  587.     {
  588.     PRINT_DEB ("Init_VM_Manager: Couldn't enter task", 0L);
  589.     return (rc);
  590.     }
  591.   }
  592.  
  593. if ((rc = EnterTask (PREPAGER_NAME, USE_NEVER, USE_NEVER, CNOSWAP, INSERT_FRONT)) != SUCCESS)
  594.   {
  595.   PRINT_DEB ("Init_VM_Manager: Couldn't enter prepager", 0L);
  596.   return (rc);
  597.   }
  598.  
  599.  
  600. if (CxParams != NULL)
  601.   {
  602.   if ((rc = EnterTask (FilePart (CxParams->PrefsPath), USE_NEVER, USE_NEVER, CNOSWAP, INSERT_FRONT)) != SUCCESS)
  603.     {
  604.     PRINT_DEB ("Init_VM_Manager: Couldn't enter preferences task", 0L);
  605.     return (rc);
  606.     }
  607.   }
  608.  
  609. VMFreeCounter = COLLECT_INTERVAL;
  610.  
  611. if (!FindDevParams (PartitionName, &PagingDevParams))
  612.   {
  613.   PRINT_DEB ("VM_Manager: Couldn't get partition information", 0L);
  614.   return (ERR_VOLUME_NOT_FOUND);
  615.   }
  616.  
  617. PRINT_DEB ("VM_Manager: Found Device params", 0L);
  618.  
  619. if ((CurrentConfig.PageDev == PD_PART) && (PagingDevParams.SysTask != NULL) && 
  620.     (!Inhibit (PartWithColon, DOSTRUE)))
  621.   {
  622.   PRINT_DEB ("VM_Manager: Couldn't inhibit paging partition", 0L);
  623.   return (ERR_INHIBIT_FAILED);
  624.   }
  625.  
  626. if ((rc = LaunchPrePager ()) != SUCCESS)
  627.   {
  628.   PRINT_DEB ("VM_Manager: Couldn't create prepager", 0L);
  629.   /* Error msg has already been posted */
  630.   return (rc);
  631.   }
  632.  
  633. if ((rc = LaunchPageHandler ()) != SUCCESS)
  634.   {
  635.   PRINT_DEB ("VM_Manager: Couldn't create page handler", 0L);
  636.   return (rc);
  637.   }
  638.  
  639. if (CurrentConfig.StatEnabled && (rc = LaunchStat ()) != SUCCESS)
  640.   {
  641.   PRINT_DEB ("VM_Manager: Couldn't init stat", 0L);
  642.   /* Error msg has already been posted */
  643.   return (rc);
  644.   }
  645.  
  646. PRINT_DEB ("VM_Manager: All tasks launched", 0L);
  647.   
  648. SetTaskPri (FindTask (NULL), 5L);
  649.  
  650. if (CurrentConfig.PageDev != PD_FILE)
  651.   adjust_priority ();
  652.  
  653. CfgChangeNotify.nr_Name = CFG_FILENAME;
  654. CfgChangeNotify.nr_Flags = NRF_SEND_SIGNAL;
  655. CfgChangeNotify.nr_stuff.nr_Signal.nr_Task = FindTask (NULL);
  656. CfgChangeNotify.nr_stuff.nr_Signal.nr_SignalNum = CfgChangeSignal;
  657. StartNotify (&CfgChangeNotify);
  658.  
  659. patch ();
  660.  
  661. AddedMemSize = (NUM_PTR_TABLES * POINTERS_PER_TABLE * PAGES_PER_TABLE - 1)
  662.                 * PAGESIZE;
  663.  
  664. NeededForTables = ALIGN_UP (PartSize / (PAGESIZE / sizeof (ULONG)), PAGESIZE);
  665.  
  666. PRINT_DEB ("Needed for tables: %lx", NeededForTables);
  667.  
  668. if (PartSize - NeededForTables < AddedMemSize)
  669.   AddedMemSize = PartSize - NeededForTables;
  670.  
  671. VirtMem = (struct MemHeader*)VirtAddrStart;
  672. VirtAddrEnd = VirtAddrStart + AddedMemSize;
  673. PRINT_DEB ("Setting VirtAddrEnd to %08lx", VirtAddrEnd);
  674.  
  675. /* If the VM_Manager is started from StartVMM40, the memory list is 
  676.  * installed in the system memory pool. Otherwise the manager was started
  677.  * by the init routine of vmm.library. Then the memory header is simply
  678.  * initialized but not added to the system
  679.  */
  680.  
  681. if (FindPort (STARTER_PORT_STD))
  682.   {
  683.   AddMemList (AddedMemSize, MEMF_FAST, CurrentConfig.VMPriority, 
  684.               (APTR)VirtAddrStart, MEMLISTNAME);
  685.   }
  686. else
  687.   {
  688.   VirtMem->mh_Node.ln_Type = NT_MEMORY;
  689.   VirtMem->mh_Node.ln_Name = NULL;      /* Marker for not added to system pool */
  690.   VirtMem->mh_Node.ln_Pri  = CurrentConfig.VMPriority;
  691.   VirtMem->mh_Attributes   = MEMF_FAST;
  692.   VirtMem->mh_First = (struct MemChunk*)(VirtAddrStart + sizeof (struct MemHeader));
  693.   VirtMem->mh_Lower = (void*)(VirtAddrStart + sizeof (struct MemHeader));
  694.   VirtMem->mh_Upper = (void*)(VirtAddrStart + AddedMemSize);
  695.   VirtMem->mh_Free  = AddedMemSize - sizeof (struct MemHeader);
  696.   VirtMem->mh_First->mc_Next = NULL;
  697.   VirtMem->mh_First->mc_Bytes = AddedMemSize - sizeof (struct MemHeader);
  698.   }
  699.  
  700. PRINT_DEB ("VM_Manager: AddedMemSize = %ld", AddedMemSize);
  701.  
  702. return (SUCCESS);
  703. }
  704.  
  705. /*********************************************************************/
  706.  
  707. PRIVATE void CloseLibs (void)
  708.  
  709. {
  710. if (DOSBase != NULL)
  711.   CloseLibrary ((struct Library*)DOSBase);
  712.  
  713. if (IntuitionBase != NULL)
  714.   CloseLibrary (IntuitionBase);
  715.  
  716. if (GfxBase != NULL)
  717.   CloseLibrary ((struct Library*)GfxBase);
  718.  
  719. if (UtilityBase != NULL)
  720.   CloseLibrary (UtilityBase);
  721.  
  722. if (ExpansionBase != NULL)
  723.   CloseLibrary (ExpansionBase);
  724.  
  725. if (CxBase != NULL)
  726.   CloseLibrary (CxBase);
  727.  
  728. if (RexxSysBase != NULL)
  729.   CloseLibrary (RexxSysBase);
  730.  
  731. if (LocaleBase != NULL)
  732.   {
  733.   CloseLibrary (LocaleBase);
  734.   LocaleBase = NULL;
  735.   }
  736. }
  737.  
  738. /*********************************************************************/
  739.  
  740. PRIVATE void InstallFreeMemAfterExit (void)
  741.  
  742. {
  743. /* The following is very ugly, but I haven't found a better way to install
  744.  * a routine that stays alive after exit.
  745.  */
  746.  
  747. extern ULONG FreeMemAfterExit,
  748.              FreeMemAfterExitEnd,
  749.              PatchLoc1,
  750.              PatchLoc2,
  751.              PatchLoc3,
  752.              ExecFreeMem,
  753.              RemainingBytes;
  754. ULONG NewFreeMem,
  755.       NewPatchLoc1,
  756.       NewPatchLoc2,
  757.       NewPatchLoc3,
  758.       NewExecFreeMem,
  759.       NewRemainingBytes;
  760.  
  761. NewFreeMem = (ULONG)DoOrigAllocMem ((ULONG)&FreeMemAfterExitEnd - (ULONG)&FreeMemAfterExit,
  762.                        MEMF_PUBLIC);
  763. if (NewFreeMem == NULL)
  764.   {
  765.   PRINT_DEB ("PANIC: Not enough memory for FreeMemAfterExit", 0L);
  766.   return;
  767.   }
  768.  
  769. CopyMem ((ULONG*)&FreeMemAfterExit, (ULONG*)NewFreeMem,
  770.          (ULONG)&FreeMemAfterExitEnd - (ULONG)&FreeMemAfterExit);
  771.  
  772. NewPatchLoc1 = (ULONG)&PatchLoc1 - (ULONG)&FreeMemAfterExit + NewFreeMem + 2;
  773. NewPatchLoc2 = (ULONG)&PatchLoc2 - (ULONG)&FreeMemAfterExit + NewFreeMem + 2;
  774. NewPatchLoc3 = (ULONG)&PatchLoc3 - (ULONG)&FreeMemAfterExit + NewFreeMem + 2;
  775. NewExecFreeMem = (ULONG)&ExecFreeMem - (ULONG)&FreeMemAfterExit + NewFreeMem;
  776. NewRemainingBytes = (ULONG)&RemainingBytes - (ULONG)&FreeMemAfterExit + NewFreeMem;
  777.  
  778. *(ULONG*)NewExecFreeMem = (ULONG)OrigFreeMem;
  779. *(ULONG*)NewPatchLoc1   = VirtAddrEnd;
  780. *(ULONG*)NewPatchLoc2   = VirtAddrStart;
  781. *(ULONG*)NewPatchLoc3   = (ULONG)(RootTable + ROOTINDEX (VirtAddrStart));
  782. *(ULONG*)NewRemainingBytes = AddedMemSize - sizeof (struct MemHeader) - 
  783.                              VirtMem->mh_Free;
  784.  
  785. OrigFreeMem = (void (*) ())NewFreeMem;
  786.  
  787. CacheClearU ();
  788. }
  789.  
  790. /*********************************************************************/
  791.  
  792. PRIVATE void InstallColdRebootAfterExit (void)
  793.  
  794. {
  795. /* The following is very ugly, but I haven't found a better way to install
  796.  * a routine that stays alive after exit.
  797.  */
  798.  
  799. extern ULONG ColdRebootPatchStart,
  800.              ColdRebootPatchEnd,
  801.              PatchLoc4;
  802. ULONG NewColdReboot,
  803.       NewPatchLoc4;
  804.  
  805. PRINT_DEB ("Installing cold reboot patch after exit", 0L);
  806. NewColdReboot = (ULONG)DoOrigAllocMem ((ULONG)&ColdRebootPatchEnd - 
  807.                                        (ULONG)&ColdRebootPatchStart,
  808.                                        MEMF_PUBLIC);
  809. if (NewColdReboot == NULL)
  810.   {
  811.   PRINT_DEB ("PANIC: Not enough memory for ColdRebootAfterExit", 0L);
  812.   return;
  813.   }
  814.  
  815. CopyMem ((ULONG*)&ColdRebootPatchStart, (ULONG*)NewColdReboot,
  816.          (ULONG)&ColdRebootPatchEnd - (ULONG)&ColdRebootPatchStart);
  817.  
  818. NewPatchLoc4 = (ULONG)&PatchLoc4 - (ULONG)&ColdRebootPatchStart + NewColdReboot + 2;
  819.  
  820. *(ULONG*)NewPatchLoc4   = (ULONG)OrigColdReboot;
  821. *(UWORD*)(NewPatchLoc4 - 2) = 0x2f3c;        /* move.l      #dummy,-(sp) */
  822.  
  823. OrigColdReboot = (void (*) ())NewColdReboot;
  824.  
  825. CacheClearU ();
  826. }
  827.  
  828. /*********************************************************************/
  829.  
  830. PRIVATE void unpatch (void)
  831.  
  832. {
  833. if (OrigSwitch != NULL)
  834.   {
  835.   Forbid ();
  836.   PRINT_DEB ("Undoing patches", 0L);
  837.   SetFunction ((struct Library*)SysBase, -0x2fa, (ULONG (*) ()) OrigCachePreDMA);
  838.   SetFunction ((struct Library*)SysBase, -0x300, (ULONG (*) ()) OrigCachePostDMA);
  839.   SetFunction ((struct Library*)SysBase,  -0x36, (ULONG (*) ()) OrigSwitch);
  840.   SetFunction ((struct Library*)SysBase, -0x11a, (ULONG (*) ()) OrigAddTask);
  841.   SetFunction ((struct Library*)SysBase, -0x13e, (ULONG (*) ()) OrigWait);
  842.   SetFunction ((struct Library*)SysBase,  -0xd8, (ULONG (*) ()) OrigAvailMem);
  843.   SetFunction ((struct Library*)SysBase,  -0xd2, (ULONG (*) ()) OrigFreeMem);
  844.   SetFunction ((struct Library*)SysBase,  -0xc6, (ULONG (*) ()) OrigAllocMem);
  845.   SetFunction ((struct Library*)DOSBase,  -0x96, (ULONG (*) ()) OrigLoadSeg);
  846.   SetFunction ((struct Library*)DOSBase, -0x300, (ULONG (*) ()) OrigNewLoadSeg);
  847. #ifdef DEBUG
  848.   SetFunction ((struct Library*)SysBase, -0x120, (ULONG (*) ()) OrigRemTask);
  849. /*  SetFunction ((struct Library*)SysBase, -0x2dc, (ULONG (*) ()) OrigStackSwap); */
  850.   SetFunction ((struct Library*)DOSBase, -0x1e,  (ULONG (*) ()) OrigOpen);
  851. #endif
  852.   if (ProcessorType == PROC_68030)
  853.     SetFunction ((struct Library*)SysBase, -0x2d6, (ULONG (*) ()) OrigColdReboot);
  854.   if (CurrentConfig.PatchWB)
  855.     SetFunction ((struct Library*)IntuitionBase, -0x114, 
  856.                  (ULONG (*) ()) OrigSetWindowTitles);
  857.   Permit ();
  858.   }
  859. }
  860.  
  861. /*********************************************************************/
  862.  
  863. PRIVATE void UninstallAsCommodity (void)
  864.  
  865. {
  866. struct Message *Msg;
  867.  
  868. PRINT_DEB ("Uninstalling commodity", 0L);
  869.  
  870. if (CxParams == NULL)
  871.   return;
  872.  
  873. if (CxParams->Broker != NULL)
  874.   DeleteCxObjAll (CxParams->Broker);
  875.  
  876. if (ExtCxPort != NULL)
  877.   {
  878.   RemPort (&(ExtCxPort->CxPort));
  879.   while ((Msg = GetMsg (&(ExtCxPort->CxPort))) != NULL)
  880.     ReplyMsg (Msg);
  881.  
  882.   FreeSignal ((LONG)ExtCxPort->CxPort.mp_SigBit);
  883.  
  884.   FreeVec (ExtCxPort->CxPort.mp_Node.ln_Name);
  885.   FreeMem (ExtCxPort, sizeof (struct ExtPort));
  886.   }
  887.  
  888. FreeVec (CxParams);
  889. }
  890.  
  891. /**********************************************************************/
  892.  
  893. void Cleanup_VM_Manager ()
  894.  
  895. {
  896. int rc;
  897.  
  898. if (VirtMem != NULL)
  899.   EndNotify (&CfgChangeNotify);
  900. FreeSignal ((LONG)CfgChangeSignal);
  901. FreeSignal ((LONG)LockAckSignal);
  902.  
  903. if (VirtMem != NULL && VirtMem->mh_Node.ln_Name != NULL)
  904.   {
  905.   Forbid ();
  906.   Remove ((struct Node*)VirtMem);
  907.   Permit ();
  908.   }
  909.  
  910. if (EarlyExit)
  911.   {
  912.   InstallFreeMemAfterExit ();
  913.   if (ProcessorType == PROC_68030)
  914.     InstallColdRebootAfterExit ();
  915.   }
  916.  
  917. unpatch ();
  918.  
  919. UninstallAsCommodity ();
  920.  
  921. if ((rc = SwitchFastROM (FALSE)) != SUCCESS)
  922.   RunTimeError (rc);
  923.  
  924. while (FindTask (WBUF_ALLOC_NAME) || FindTask (GARBAGE_COLL_NAME))
  925.   Delay (1L);
  926.  
  927. if (CurrentConfig.StatEnabled && FindTask (STAT_NAME))
  928.   {
  929.   Signal (StatTask, 1L << StatQuitSignal);
  930.   while (FindTask (STAT_NAME))
  931.     Delay (1L);
  932.   }
  933.  
  934. if (FindTask (PREPAGER_NAME))
  935.   {
  936.   Signal (PrePagerTask, 1L << PrePagerQuitSignal);
  937.   while (FindTask (PREPAGER_NAME))
  938.     Delay (1L);
  939.   }
  940.  
  941. if (FindTask (PAGEHANDLER_NAME))
  942.   {
  943.   Signal (PageHandlerTask, 1L << PageHandlerQuitSignal);
  944.   while (FindTask (PAGEHANDLER_NAME))
  945.     Delay (1L);
  946.   }
  947.  
  948. while (FindTask (ERR_NAME))
  949.   Delay (1L);
  950.  
  951. PRINT_DEB ("VM_Manager: All subtasks terminated", 0L);
  952.  
  953. /* Wait until all users of the patched routines have finished */
  954. while ((AllocMemUsers != 0) || (VirtMem != NULL && VirtMemSema.ss_Owner != NULL))
  955.   Delay (1L);
  956.  
  957. PRINT_DEB ("All users of patched routines exited", 0L);
  958.  
  959. if (VirtAddrStart != NULL)
  960.   {
  961. /**********************************************************************
  962.  *                     This doesn't work in OS3.0
  963.  * PRINT_DEB ("VM_Manager: Freeing slot %lx", VirtAddrStart >> E_SLOTSHIFT);
  964.  * FreeExpansionMem (VirtAddrStart >> E_SLOTSHIFT, NUM_PTR_TABLES * 0x200L);
  965.  **********************************************************************/
  966.   }
  967.  
  968. if ((CurrentConfig.PageDev == PD_PART) && (PartitionName [0] != 0) && 
  969.     (PagingDevParams.SysTask != NULL))
  970.   {
  971.   if (Inhibit (PartWithColon, FALSE))
  972.     PRINT_DEB ("Successfully removed inhibit", 0L);
  973.   else
  974.     PRINT_DEB ("Couldn't remove inhibit", 0L);
  975.   }
  976.  
  977. KillTrackInfo ();
  978.  
  979. PRINT_DEB ("Killing task table", 0L);
  980. KillTaskTable ();
  981.  
  982. if (RexxPort)
  983.   {
  984.   if (RexxPort->mp_Node.ln_Name != NULL)
  985.     RemPort (RexxPort);
  986.   DeleteMsgPort (RexxPort);
  987.   }
  988.  
  989. if (VMPort)
  990.   {
  991.   if (VMPort->mp_Node.ln_Name != NULL)
  992.     RemPort (VMPort);
  993.   DeleteMsgPort (VMPort);
  994.   }
  995.  
  996. if (InitPort)
  997.   DeleteMsgPort (InitPort);
  998.  
  999. if (!EarlyExit)
  1000.   {
  1001.   PRINT_DEB ("Killing MMU table", 0L);
  1002.   KillMMUTable ();
  1003.   }
  1004.  
  1005. CloseVMMCatalog ();
  1006.  
  1007. PRINT_DEB ("VM_Manager: Exiting", 0L);
  1008.  
  1009. #ifdef DEBUG
  1010. CloseDebugWindow ();
  1011. #endif
  1012.  
  1013. CloseLibs ();
  1014. }
  1015.